<!DOCTYPE html>



  


<html class="theme-next gemini use-motion" lang="zh-Hans">
<head>
  <meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
<meta name="theme-color" content="#222">









<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />
















  
  
  <link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css" />







<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css" />

<link href="/css/main.css?v=5.1.4" rel="stylesheet" type="text/css" />


  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png?v=5.1.4">


  <link rel="mask-icon" href="/images/logo.svg?v=5.1.4" color="#222">





  <meta name="keywords" content="spring," />










<meta name="description" content="Spring技术体系结构 单一架构：主要框架为Spring、SpringMVC、Mybatis    分布式架构：SpringBoot（是对SSM的简化），SpringCloud、中间件  ​	多个模块，每一个模块都是运行在自己的Tomcat上，模块之间可以互相调用。每一个模块可以看做是一个单一架构应用。  框架&#x3D;jar包+配置文件 框架可以定制化配置 一、SpringFramework">
<meta property="og:type" content="article">
<meta property="og:title" content="Spring">
<meta property="og:url" content="https://gitee.com/htt-sub/htt-sub/2023/10/24/Spring/index.html">
<meta property="og:site_name" content="黄宏涛">
<meta property="og:description" content="Spring技术体系结构 单一架构：主要框架为Spring、SpringMVC、Mybatis    分布式架构：SpringBoot（是对SSM的简化），SpringCloud、中间件  ​	多个模块，每一个模块都是运行在自己的Tomcat上，模块之间可以互相调用。每一个模块可以看做是一个单一架构应用。  框架&#x3D;jar包+配置文件 框架可以定制化配置 一、SpringFramework">
<meta property="og:locale">
<meta property="og:image" content="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231024131114712.png">
<meta property="og:image" content="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231024131540544.png">
<meta property="og:image" content="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231024132052232.png">
<meta property="og:image" content="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231024132826704.png">
<meta property="og:image" content="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231024135933265.png">
<meta property="og:image" content="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231024195405181.png">
<meta property="og:image" content="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231025083446449.png">
<meta property="og:image" content="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231025085517874.png">
<meta property="og:image" content="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231025100436326.png">
<meta property="og:image" content="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231025101047805.png">
<meta property="og:image" content="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231025143927507.png">
<meta property="og:image" content="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231025154616460.png">
<meta property="og:image" content="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231026212602884.png">
<meta property="og:image" content="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231027085356334.png">
<meta property="og:image" content="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231027092230348.png">
<meta property="og:image" content="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231027095757104.png">
<meta property="og:image" content="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231027133557662.png">
<meta property="og:image" content="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231027141324103.png">
<meta property="og:image" content="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231027185441163.png">
<meta property="og:image" content="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231027190507813.png">
<meta property="og:image" content="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231027191230876.png">
<meta property="og:image" content="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231027191626944.png">
<meta property="og:image" content="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231027192121789.png">
<meta property="og:image" content="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231027212940767.png">
<meta property="og:image" content="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231027213930981.png">
<meta property="og:image" content="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231027214123267.png">
<meta property="article:published_time" content="2023-10-24T02:34:41.000Z">
<meta property="article:modified_time" content="2023-10-30T05:08:50.303Z">
<meta property="article:author" content="黄宏涛">
<meta property="article:tag" content="spring">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231024131114712.png">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '',
    scheme: 'Gemini',
    version: '5.1.4',
    sidebar: {"position":"post","display":"post","offset":12,"b2t":false,"scrollpercent":false,"onmobile":false},
    fancybox: true,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    duoshuo: {
      userId: '0',
      author: '博主'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="https://gitee.com/htt-sub/htt-sub/2023/10/24/Spring/"/>





  <title>Spring | 黄宏涛</title>
  








<meta name="generator" content="Hexo 6.3.0"></head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">

  
  
    
  

  <div class="container sidebar-position-post page-post-detail">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/"  class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">黄宏涛</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <p class="site-subtitle"></p>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br />
            
            首页
          </a>
        </li>
      
        
        <li class="menu-item menu-item-categories">
          <a href="/categories/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-th"></i> <br />
            
            分类
          </a>
        </li>
      
        
        <li class="menu-item menu-item-tags">
          <a href="/tags/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-tags"></i> <br />
            
            标签
          </a>
        </li>
      

      
    </ul>
  

  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://gitee.com/htt-sub/htt-sub/2023/10/24/Spring/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/images/avatar.png">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="黄宏涛">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">Spring</h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2023-10-24T10:34:41+08:00">
                2023-10-24
              </time>
            

            

            
          </span>

          
            <span class="post-category" >
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/SSM/" itemprop="url" rel="index">
                    <span itemprop="name">SSM</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        <h1 id="Spring"><a href="#Spring" class="headerlink" title="Spring"></a>Spring</h1><h2 id="技术体系结构"><a href="#技术体系结构" class="headerlink" title="技术体系结构"></a>技术体系结构</h2><ol>
<li>单一架构：主要框架为Spring、SpringMVC、Mybatis</li>
</ol>
<p><img src="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231024131114712.png" alt="image-20231024131114712"></p>
<ol start="2">
<li>分布式架构：SpringBoot（是对SSM的简化），SpringCloud、中间件</li>
</ol>
<p>​	多个模块，每一个模块都是运行在自己的Tomcat上，模块之间可以互相调用。每一个模块可以看做是一个单一架构应用。</p>
<p><img src="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231024131540544.png" alt="image-20231024131540544"></p>
<p><strong>框架&#x3D;jar包+配置文件</strong></p>
<p>框架可以定制化配置</p>
<h2 id="一、SpringFramework介绍"><a href="#一、SpringFramework介绍" class="headerlink" title="一、SpringFramework介绍"></a>一、SpringFramework介绍</h2><p><img src="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231024132052232.png" alt="image-20231024132052232"></p>
<ol>
<li>Core Container：核心容器，创建、管理和存储对象（<strong>组件对象，如添加了@Component和@Controller注解等</strong>）</li>
<li>AOP&amp;Aspect： <strong>面向切面编程</strong></li>
<li>TX： <strong>声明式事务管理</strong> </li>
<li>SpringMVC： 提供了<strong>面向Web应用程序功能</strong></li>
</ol>
<h3 id="1-Spring优势"><a href="#1-Spring优势" class="headerlink" title="1. Spring优势"></a>1. Spring优势</h3><ol>
<li>生态丰富，支持许多模块和库，SpringBoot、SpringSecurity、SpringCloud</li>
<li>模块化的设计：框架组件之间松散耦合和模块化设计，具有更好的重用性，可拓展性和维护性。</li>
<li>简化Java开发</li>
</ol>
<h2 id="二、SpringIOC容器和核心概念"><a href="#二、SpringIOC容器和核心概念" class="headerlink" title="二、SpringIOC容器和核心概念"></a>二、SpringIOC容器和核心概念</h2><h3 id="1-组件"><a href="#1-组件" class="headerlink" title="1. 组件"></a>1. 组件</h3><p><img src="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231024132826704.png" alt="image-20231024132826704"></p>
<h3 id="2-期待"><a href="#2-期待" class="headerlink" title="2. 期待"></a>2. 期待</h3><ol>
<li>有人替我创建组件对象</li>
<li>有人替我保存组件对象</li>
<li>有人替我自动组装</li>
<li>有人替我管理事务</li>
<li>有人替我整合其它框架</li>
</ol>
<h3 id="3-Spring组件管理动作"><a href="#3-Spring组件管理动作" class="headerlink" title="3. Spring组件管理动作"></a>3. Spring组件管理动作</h3><ol>
<li>组件对象实例化</li>
<li>组件属性复制</li>
<li>组件对象之间引用</li>
<li>组件对象存活周期管理</li>
</ol>
<p>需要<strong>配置文件</strong>告诉<strong>Spring管理</strong>哪些<strong>组件和它们的关系</strong></p>
<h3 id="4-SpringIOC容器和容器实现"><a href="#4-SpringIOC容器和容器实现" class="headerlink" title="4. SpringIOC容器和容器实现"></a>4. SpringIOC容器和容器实现</h3><p>Tomcat也是一个容器</p>
<h3 id="5-SpringIOC容器接口"><a href="#5-SpringIOC容器接口" class="headerlink" title="5. SpringIOC容器接口"></a>5. SpringIOC容器接口</h3><p><strong>BeanFactory</strong>接口提供另一个高级配置机制，能够<strong>管理任何类型对象</strong>。</p>
<p><strong>ApplicationContext</strong>是<strong>BeanFactory</strong>的子接口。拓展了以下功能：</p>
<ul>
<li>更容易与Spring的<strong>AOP</strong>功能集成</li>
<li>消息资源处理（国际化）</li>
<li>特定接口的实现，例如Web应用程序的<strong>WebApplicationContext</strong>，添加了更多特定于企业的功能。</li>
</ul>
<p><strong>ApplicationContext容器实现类</strong>：</p>
<ul>
<li><strong>ClassPathXmlApplicationContext</strong>：通过读取类路径下的XML格式的配置文件创建IOC容器对象</li>
<li>FileSystemXmlApplicationContext：通过文件系统路径读取XML格式的配置文件创建IOC容器对象</li>
<li><strong>AnnotationConfigApplicationContext</strong>：通过读取Java配置类创建IOC容器对象</li>
<li><strong>WebApplicationContext（常用）</strong>:  专为Web应用准备，基于Web环境创建IOC容器对象</li>
</ul>
<p><img src="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231024135933265.png" alt="image-20231024135933265"></p>
<h3 id="6-三种配置方式"><a href="#6-三种配置方式" class="headerlink" title="6. 三种配置方式"></a>6. <strong>三种配置方式</strong></h3><p>Spring框架提供了多种配置方式：<strong>XML配置方式</strong>、<strong>注解方式</strong>和<strong>Java配置类方式</strong>。</p>
<ol>
<li>注解方式：通过在Bean类加上相应注解（如**@Component,@Service,@Autowired等<strong>），</strong>将Bean注册到SpringIOC容器<strong>，这样</strong>容器就可以管理这些Bean的依赖关系**。</li>
<li>Java配置类方式：通过Java类来定义Bean、Bean之间的依赖关系和配置关系，代替XML配置文件的方式。<strong>Java配置类</strong>是一种使用<strong>Java编写配置信息方式</strong>，通过**@Configuration、@Bean等注解来实现Bean和依赖关系的配置**。</li>
</ol>
<p>推荐使用： <strong>配置类+注解方式</strong></p>
<h3 id="7-Spring-IoC-DI-概念"><a href="#7-Spring-IoC-DI-概念" class="headerlink" title="7. Spring IoC&#x2F; DI 概念"></a>7. Spring IoC&#x2F; DI 概念</h3><p><strong>IOC容器：</strong></p>
<p>负责对象的创建、管理、装配。容器通过读取配置数据来获取有关要实例化、配置和组装组件的指令。</p>
<p><strong>IOC控制反转</strong>（<strong>内部是反射</strong>）：</p>
<p>当应用程序需要使用一个对象时，<strong>不再是应用程序直接创建该对象，而是由IOC容器来创建和管理</strong>，即<strong>控制权</strong>由应用程序转移到<strong>IoC容器</strong>，也就是反转了控制权。</p>
<p>控制反转是通过依赖查找实现的。</p>
<p><strong>依赖注入（DI）：</strong></p>
<p>组件之间传递依赖关系，将依赖关系在容器内部处理，把<strong>一个对象注入到另一个对象内</strong>（通过<strong>构造函数注入</strong>、<strong>Setter方法注入</strong>、<strong>接口注入</strong>）</p>
<h2 id="三、SpringIOC实践和应用"><a href="#三、SpringIOC实践和应用" class="headerlink" title="三、SpringIOC实践和应用"></a>三、SpringIOC实践和应用</h2><h3 id="SpringIoC实现步骤"><a href="#SpringIoC实现步骤" class="headerlink" title="SpringIoC实现步骤"></a>SpringIoC实现步骤</h3><ul>
<li>第一步：编写配置文件（XML、配置类、注解），配置文件包含<strong>组件类信息</strong>、<strong>组件之间的引用关系</strong>。</li>
<li>第二步：实例化IoC容器对象，并指定配置文件</li>
<li>第三步：如何在Java获取组件，使用</li>
</ul>
<h3 id="基于XML配置方式组件管理"><a href="#基于XML配置方式组件管理" class="headerlink" title="基于XML配置方式组件管理"></a>基于XML配置方式组件管理</h3><p><img src="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231024195405181.png" alt="image-20231024195405181"></p>
<h4 id="基于XML的IoC配置"><a href="#基于XML的IoC配置" class="headerlink" title="基于XML的IoC配置"></a>基于XML的IoC配置</h4><p>自己如何实例化对象：</p>
<ol>
<li>构造函数实例化（new 类名）：（无参构造函数，有参构造函数(类似于DI)）</li>
<li>工厂模式实例化：（静态工厂、非静态工厂）</li>
</ol>
<p><strong>右键new, XML configuration file</strong>快速生成带约束的XML配置文件</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;UTF-8&quot;</span>?&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">beans</span> <span class="attr">xmlns</span>=<span class="string">&quot;http://www.springframework.org/schema/beans&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:xsi</span>=<span class="string">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xsi:schemaLocation</span>=<span class="string">&quot;http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">beans</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p><strong>无参构造函数实例化</strong></p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--无参数构造函数</span></span><br><span class="line"><span class="comment">        bean代表一个组件，Class表示类的权限定符</span></span><br><span class="line"><span class="comment">        一个组件类声明了两个组件信息-[默认单例模式]- 会实例化两个组件对象</span></span><br><span class="line"><span class="comment">    --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;happyComponent1&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.example.ioc.HappyComponent&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;happyComponent2&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.example.ioc.HappyComponent&quot;</span>/&gt;</span></span><br></pre></td></tr></table></figure>

<p><strong>静态工厂方法实例化</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">静态工厂类</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ClientService</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> ClientService clientService=<span class="keyword">new</span> <span class="title class_">ClientService</span>();</span><br><span class="line">    <span class="keyword">private</span> <span class="title function_">ClientService</span><span class="params">()</span>&#123;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 通过静态工厂方法获取当前类的对象</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> ClientService <span class="title function_">createInstance</span><span class="params">()</span>&#123;</span><br><span class="line">        <span class="keyword">return</span> clientService;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--静态工厂类如何声明工厂方法进行IoC的配置</span></span><br><span class="line"><span class="comment">        factory-method必须指定静态工厂方法</span></span><br><span class="line"><span class="comment">    --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;clientService&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.example.ioc.ClientService&quot;</span> <span class="attr">factory-method</span>=<span class="string">&quot;createInstance&quot;</span>/&gt;</span></span><br></pre></td></tr></table></figure>

<p><strong>非静态方法实例化</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">DefaultServleLocator</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> ClientServieImpl clientServie=<span class="keyword">new</span> <span class="title class_">ClientServieImpl</span>();</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 非静态工厂方法，返回一个其它类的实例，方法必须非static</span></span><br><span class="line">    <span class="keyword">public</span> ClientServieImpl <span class="title function_">createClientServiceInstance</span><span class="params">()</span>&#123;</span><br><span class="line">        <span class="keyword">return</span> clientServie;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--非静态工厂对象，配置工厂类的组件信息--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;defaultServleLocator&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.example.ioc.DefaultServleLocator&quot;</span>/&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!--通过指定非静态工厂对象和方法名，配置IoC信息--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;clientServie2&quot;</span> <span class="attr">factory-bean</span>=<span class="string">&quot;defaultServleLocator&quot;</span> <span class="attr">factory-method</span>=<span class="string">&quot;createClientServiceInstance&quot;</span>/&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="基于XML的DI配置"><a href="#基于XML的DI配置" class="headerlink" title="基于XML的DI配置"></a>基于XML的DI配置</h4><p>通过配置文件实现IoC容器中<strong>Bean之间的引用</strong>（依赖注入）</p>
<p>先创建对象（ioc），再进行属性复制（DI）</p>
<ul>
<li>基于构造函数注入(<strong>了解</strong>)</li>
<li>基于Setter方法的注入</li>
</ul>
<p><strong>构造函数注入（单参）：</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UserService</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> UserDao userDao;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">UserService</span><span class="params">(UserDao userDao)</span>&#123;</span><br><span class="line">        <span class="built_in">this</span>.userDao=userDao;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UserDao</span> &#123;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--引用和被引用的组件必须全部在IoC容器--&gt;</span></span><br><span class="line"><span class="comment">&lt;!--步骤1：将它们都放在IoC容器中--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;userDao&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.example.di.UserDao&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;userService&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.example.di.UserService&quot;</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--构造参数传值</span></span><br><span class="line"><span class="comment">        value直接指定属性值 或 ref引用的其它Bean</span></span><br><span class="line"><span class="comment">    --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">constructor-arg</span> <span class="attr">ref</span>=<span class="string">&quot;userDao&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p><strong>构造函数注入（多参）：</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UserService</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> UserDao userDao;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> age;</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">UserService</span><span class="params">(<span class="type">int</span> age,String name,UserDao userDao)</span>&#123;</span><br><span class="line">        <span class="built_in">this</span>.userDao=userDao;</span><br><span class="line">        <span class="built_in">this</span>.age=age;</span><br><span class="line">        <span class="built_in">this</span>.name=name;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UserDao</span> &#123;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;userDao&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.example.di.UserDao&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;userService&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.example.di.UserService&quot;</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--方法一：按照顺序构造参数名填写--&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">constructor-arg</span> <span class="attr">value</span>=<span class="string">&quot;18&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">constructor-arg</span> <span class="attr">value</span>=<span class="string">&quot;黄宏涛&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">constructor-arg</span> <span class="attr">ref</span>=<span class="string">&quot;userDao&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;userDao&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.example.di.UserDao&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;userService&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.example.di.UserService&quot;</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--方法二：不用考虑顺序,通过name属性指定参数名--&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">constructor-arg</span> <span class="attr">name</span>=<span class="string">&quot;age&quot;</span> <span class="attr">value</span>=<span class="string">&quot;18&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">constructor-arg</span> <span class="attr">name</span>=<span class="string">&quot;name&quot;</span> <span class="attr">value</span>=<span class="string">&quot;黄宏涛&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">constructor-arg</span> <span class="attr">name</span>=<span class="string">&quot;userDao&quot;</span> <span class="attr">ref</span>=<span class="string">&quot;userDao&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;userDao&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.example.di.UserDao&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;userService&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.example.di.UserService&quot;</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--方法三：不考虑顺序，index构造参数的 从0开始--&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">constructor-arg</span> <span class="attr">index</span>=<span class="string">&quot;0&quot;</span> <span class="attr">value</span>=<span class="string">&quot;18&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">constructor-arg</span> <span class="attr">index</span>=<span class="string">&quot;1&quot;</span> <span class="attr">value</span>=<span class="string">&quot;黄宏涛&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">constructor-arg</span> <span class="attr">index</span>=<span class="string">&quot;2&quot;</span> <span class="attr">ref</span>=<span class="string">&quot;userDao&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p><strong>Setter方法依赖注入：</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UserService</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> UserDao userDao;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setName</span><span class="params">(String name)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.name = name;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setUserDao</span><span class="params">(UserDao userDao)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.userDao = userDao;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--setter方法注入--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;user1&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.example.di.UserDao&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;userService&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.example.di.UserService&quot;</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--name属性名: setter方法的去掉set和首字母小写的值  setName》》name--&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;name&quot;</span> <span class="attr">value</span>=<span class="string">&quot;黄宏涛&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;userDao&quot;</span> <span class="attr">ref</span>=<span class="string">&quot;user1&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="IoC容器创建"><a href="#IoC容器创建" class="headerlink" title="IoC容器创建"></a>IoC容器创建</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 如何创建IoC容器，并读取配置文件</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">createIoC</span><span class="params">()</span>&#123;</span><br><span class="line">        <span class="comment">/**</span></span><br><span class="line"><span class="comment">         * 接口</span></span><br><span class="line"><span class="comment">         * BeanFactory</span></span><br><span class="line"><span class="comment">         * ApplicationContext</span></span><br><span class="line"><span class="comment">         * 实现类</span></span><br><span class="line"><span class="comment">         * ClassPathXmlApplicationContext 读取XML文件方式创建ioc</span></span><br><span class="line"><span class="comment">         * FileSystemXmlApplicationContext</span></span><br><span class="line"><span class="comment">         * WebApplicationContext</span></span><br><span class="line"><span class="comment">         * AnnotationConfigApplicationContext 读取配置类方式的ioc容器</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line">        <span class="comment">// 创建容器：方法一</span></span><br><span class="line">        <span class="type">ApplicationContext</span> <span class="variable">context</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ClassPathXmlApplicationContext</span>(<span class="string">&quot;spring-01.xml&quot;</span>);</span><br><span class="line">        <span class="comment">// 创建容器：方法二</span></span><br><span class="line">        <span class="type">ClassPathXmlApplicationContext</span> <span class="variable">context1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ClassPathXmlApplicationContext</span>();</span><br><span class="line">        context1.setApplicationStartup(<span class="string">&quot;spring-01.xml&quot;</span>);</span><br><span class="line">        <span class="comment">// refresh调用，才会真正创建容器</span></span><br><span class="line">        context1.refresh();</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<h4 id="获取Bean的三种方法"><a href="#获取Bean的三种方法" class="headerlink" title="获取Bean的三种方法"></a>获取Bean的三种方法</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 如何在ioc中获取组件</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span>  <span class="title function_">getBean</span><span class="params">()</span>&#123;</span><br><span class="line">        <span class="comment">// 创建容器</span></span><br><span class="line">        <span class="type">ApplicationContext</span> <span class="variable">context</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ClassPathXmlApplicationContext</span>(<span class="string">&quot;spring-01.xml&quot;</span>);</span><br><span class="line">        <span class="comment">// 获取组件</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 方法一（不推荐）：根据BeanId获取，返回类型为Object,需要强制类型转换</span></span><br><span class="line">        <span class="type">HappyComponent</span> <span class="variable">happyComponent</span> <span class="operator">=</span> (HappyComponent) context.getBean(<span class="string">&quot;happyComponent&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 方法二 ：根据beanId,同时指定bean的类型Class</span></span><br><span class="line">        <span class="type">HappyComponent</span> <span class="variable">happyComponent1</span> <span class="operator">=</span> context.getBean(<span class="string">&quot;happyComponent&quot;</span>, HappyComponent.class);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 方法三： 根据bean类型获取（也可以为该类的接口），同一个类型可能有多个Bean</span></span><br><span class="line">        HappyComponent happyComponent2= context.getBean(HappyComponent.class);</span><br><span class="line">        </span><br><span class="line">        System.out.println(happyComponent);</span><br><span class="line">        System.out.println(happyComponent1);</span><br><span class="line">        System.out.println(happyComponent2);</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<h4 id="组件Bean的生命周期"><a href="#组件Bean的生命周期" class="headerlink" title="组件Bean的生命周期"></a>组件Bean的生命周期</h4><p><img src="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231025083446449.png" alt="image-20231025083446449"></p>
<p>周期方法的概念：<strong>当IoC容器实例化和销毁对象时调用</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">JavaBean</span> &#123;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 初始化方法：必须是public void 无参数</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">init</span><span class="params">()</span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;JavaBean初始化&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 销毁方法：必须是public void 无参数</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">destory</span><span class="params">()</span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;JavaBean销毁&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--init-method指定初始化方法</span></span><br><span class="line"><span class="comment">    destroy-method指定销毁方法</span></span><br><span class="line"><span class="comment">    SpringIoc容器会在对应的时间节点调用对应方法--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;javaBean&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.example.ioc.JavaBean&quot;</span></span></span><br><span class="line"><span class="tag">          <span class="attr">init-method</span>=<span class="string">&quot;init&quot;</span> <span class="attr">destroy-method</span>=<span class="string">&quot;destory&quot;</span></span></span><br><span class="line"><span class="tag">    /&gt;</span></span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// IoC创建完成，就会直接调用JavaBean的初始化方法</span></span><br><span class="line">        <span class="type">ClassPathXmlApplicationContext</span> <span class="variable">context</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ClassPathXmlApplicationContext</span>(<span class="string">&quot;spring-01.xml&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 正常结束Ioc容器,会调用JavaBean的销毁方法，</span></span><br><span class="line">        <span class="comment">// 若没有用close方法，Ioc会立即释放，不会调用destroy方法</span></span><br><span class="line">        context.close();</span><br></pre></td></tr></table></figure>

<h4 id="Bean的作用域"><a href="#Bean的作用域" class="headerlink" title="Bean的作用域"></a>Bean的作用域</h4><p>在Ioc容器中，**<bean>标签<strong>对应的信息会转为Spring内部的</strong>BeanDefinition对象**，BeanDefinition对象包含定义的信息（id,class等）。</p>
<p><strong>Ioc容器</strong>可以根据<strong>BeanDefinition</strong>对象<strong>反射</strong>创建多个<strong>Bean对象实例</strong>。</p>
<p>具体<strong>创建多少个Bean的实例对象</strong>，由Bean的作用域<strong>Scope属性指定</strong>。</p>
<p><img src="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231025085517874.png" alt="image-20231025085517874"></p>
<table>
<thead>
<tr>
<th>取值</th>
<th>含义</th>
<th>创建对象的时机</th>
<th>默认值</th>
</tr>
</thead>
<tbody><tr>
<td>singleton</td>
<td>Ioc容器中，这个Bean对象始终只有一个</td>
<td>Ioc容器初始化</td>
<td>是</td>
</tr>
<tr>
<td>prototype</td>
<td>Ioc容器中，Bean对象有多个</td>
<td>获取Bean时</td>
<td>否</td>
</tr>
</tbody></table>
<p>另外request和session不常用</p>
<p><strong>单例</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">JavaBean</span> <span class="variable">javaBean</span> <span class="operator">=</span> context.getBean(JavaBean.class);</span><br><span class="line">      <span class="type">JavaBean</span> <span class="variable">javaBean1</span> <span class="operator">=</span> context.getBean(JavaBean.class);</span><br><span class="line">      <span class="comment">// 多个获取同一个单例Bean对象，始终都是同一个</span></span><br><span class="line">      System.out.println(javaBean1==javaBean);</span><br></pre></td></tr></table></figure>

<p><strong>多例</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 多例，每次getBean都会创建一个新Bean对象</span></span><br><span class="line">      <span class="type">JavaBean</span> <span class="variable">javaBean</span> <span class="operator">=</span> context.getBean(JavaBean.class);</span><br><span class="line">      <span class="type">JavaBean</span> <span class="variable">javaBean1</span> <span class="operator">=</span> context.getBean(JavaBean.class);</span><br><span class="line">      System.out.println(javaBean1==javaBean);</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h4 id="factoryBean的使用"><a href="#factoryBean的使用" class="headerlink" title="factoryBean的使用"></a>factoryBean的使用</h4><p><img src="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231025100436326.png" alt="image-20231025100436326"></p>
<p>factoryBean用于<strong>配置复杂的Bean对象</strong>，可以将<strong>自定义的组件实例化</strong>存储在<strong>factoryBean</strong>的<strong>getObject方法</strong></p>
<p>factoryBean不需要再写factory-method属性。</p>
<p>使用场景：</p>
<ol>
<li>代理类的创建</li>
<li>第三方框架整合</li>
<li><strong>复杂对象实例化</strong></li>
</ol>
<p><img src="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231025101047805.png" alt="image-20231025101047805"></p>
<p>Spring整合Mybatis就是通过factoryBean实现。将复杂对象的创建过程放到了getObject方法中。我们可以直接用sqlSession</p>
<blockquote>
<p>JavaBean类</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">JavaBean</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">getName</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> name;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setName</span><span class="params">(String name)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.name = name;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">toString</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;JavaBean&#123;&quot;</span> +</span><br><span class="line">                <span class="string">&quot;name=&#x27;&quot;</span> + name + <span class="string">&#x27;\&#x27;&#x27;</span> +</span><br><span class="line">                <span class="string">&#x27;&#125;&#x27;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>JavaBeanFactory工厂类</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 制造JavaBean类的工厂</span></span><br><span class="line"><span class="comment"> * 步骤：</span></span><br><span class="line"><span class="comment"> * 1. 实现FactoryBean接口</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">JavaBeanFactory</span> <span class="keyword">implements</span> <span class="title class_">FactoryBean</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> String value;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setValue</span><span class="params">(String value)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.value = value;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> Object <span class="title function_">getObject</span><span class="params">()</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        <span class="comment">// 使用自己的方法实例化对象</span></span><br><span class="line">        <span class="type">JavaBean</span> <span class="variable">javaBean</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">JavaBean</span>();</span><br><span class="line">        javaBean.setName(value);</span><br><span class="line">        <span class="keyword">return</span> javaBean;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> Class&lt;?&gt; getObjectType() &#123;</span><br><span class="line">        <span class="keyword">return</span> JavaBean.class;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>配置文件</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--id是getObject方法返回的javaBean对象标识，class：标准化工厂类</span></span><br><span class="line"><span class="comment">        工厂Bean的标识，&amp;id</span></span><br><span class="line"><span class="comment">    --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;javaBean&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.example.ioc.JavaBeanFactory&quot;</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--此位置属性是给JavaBeanFactory配置的,可以在工厂类中添加桥接，从而给JavaBean类赋值--&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;value&quot;</span> <span class="attr">value</span>=<span class="string">&quot;黄宏涛&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>test</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">void</span>  <span class="title function_">getBean</span><span class="params">()</span>&#123;</span><br><span class="line">        <span class="type">ClassPathXmlApplicationContext</span> <span class="variable">context</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ClassPathXmlApplicationContext</span>(<span class="string">&quot;spring-01.xml&quot;</span>);</span><br><span class="line">        <span class="comment">//读取Bean</span></span><br><span class="line">        <span class="type">JavaBean</span> <span class="variable">javaBean</span> <span class="operator">=</span> context.getBean(<span class="string">&quot;javaBean&quot;</span>, JavaBean.class);</span><br><span class="line">        <span class="comment">// javaBeanFactory工厂也会加入到Ioc容器，名字为&amp;id</span></span><br><span class="line">        <span class="type">Object</span> <span class="variable">javaBeanFactory</span> <span class="operator">=</span> context.getBean(<span class="string">&quot;&amp;javaBean&quot;</span>);</span><br><span class="line">        System.out.println(javaBean);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 输出 JavaBean&#123;name=&#x27;黄宏涛&#x27;&#125;</span></span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<h4 id="BeanFactory和FactoryBean区别"><a href="#BeanFactory和FactoryBean区别" class="headerlink" title="BeanFactory和FactoryBean区别"></a>BeanFactory和FactoryBean区别</h4><ol>
<li>BeanFactory（Ioc容器）：Ioc容器顶级接口，定义了容器的基本行为</li>
<li>FactoryBean（组件Bean）:  标准化组件工厂的接口</li>
</ol>
<h3 id="基于XML-注解方式管理Bean"><a href="#基于XML-注解方式管理Bean" class="headerlink" title="基于XML+注解方式管理Bean"></a>基于XML+注解方式管理Bean</h3><p><span style="color:red">IoC容器实现<strong>ClassPathXmlApplicationContext对象</strong></span></p>
<h4 id="Bean注解标记和扫描（Ioc）"><a href="#Bean注解标记和扫描（Ioc）" class="headerlink" title="Bean注解标记和扫描（Ioc）"></a>Bean注解标记和扫描（Ioc）</h4><p>下面这四个都可以将类定义为Spring的Bean</p>
<p>默认Bean的id为<strong>类名首字母小写</strong></p>
<table>
<thead>
<tr>
<th>@Component</th>
<th>仅仅表示该类为容器中一个组件</th>
</tr>
</thead>
<tbody><tr>
<td>@Repository</td>
<td>用于数据访问层Dao，标记类为容器中Bean，与@Component功能相同</td>
</tr>
<tr>
<td>@Service</td>
<td>用于业务层Service，标记类为容器中Bean，与@Component功能相同</td>
</tr>
<tr>
<td>@Controller</td>
<td>用于控制层Controller，标记类为容器中Bean，与@Component功能相同</td>
</tr>
</tbody></table>
<p><strong>使用步骤：</strong></p>
<ol>
<li><p>定义注解</p>
</li>
<li><p>扫描指定包，使注解生效</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&lt;!--配置包扫描,指定Ioc容器去哪些包查找注解类--&gt;</span><br><span class="line">    &lt;context:component-scan base-<span class="keyword">package</span>=<span class="string">&quot;org.example.controller&quot;</span>/&gt;</span><br><span class="line">&lt;!--也可以排除指定包--&gt;</span><br></pre></td></tr></table></figure></li>
</ol>
<h4 id="组件Bean作用域和周期方法"><a href="#组件Bean作用域和周期方法" class="headerlink" title="组件Bean作用域和周期方法"></a>组件Bean作用域和周期方法</h4><p><strong>周期方法和作用域:</strong></p>
<p>会在getBean()调用该类时执行初始化方法。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="comment">// 指定作用域：表示容器通过getBean可以创建该类的多个对象</span></span><br><span class="line"><span class="meta">@Scope(scopeName = ConfigurableBeanFactory.SCOPE_PROTOTYPE)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">User</span> &#123;</span><br><span class="line">    <span class="meta">@PostConstruct</span>  <span class="comment">//指定初始化方法</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">init</span><span class="params">()</span>&#123;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@PreDestroy</span>   <span class="comment">//指定销毁方法</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">destroy</span><span class="params">()</span>&#123;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h4 id="Bean属性赋值-引用类型自动装配DI"><a href="#Bean属性赋值-引用类型自动装配DI" class="headerlink" title="Bean属性赋值: 引用类型自动装配DI"></a>Bean属性赋值: 引用类型自动装配DI</h4><p>userService</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">UserService</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">show</span><span class="params">()</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>userServiceImpl</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UserServiceImpl</span> <span class="keyword">implements</span> <span class="title class_">UserService</span> &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">show</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;userService的show方法&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>userController</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Controller</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UserController</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 自动装配，对应类型的Bean</span></span><br><span class="line"><span class="comment">     * 默认为true：必须有对应的组件</span></span><br><span class="line"><span class="comment">     * false：可以没有对应组件，为null</span></span><br><span class="line"><span class="comment">     * 步骤：</span></span><br><span class="line"><span class="comment">     * 1. Ioc容器中查找userService接口对应的实现类对象</span></span><br><span class="line"><span class="comment">     * 2. 设置给当前属性</span></span><br><span class="line"><span class="comment">      */</span></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="comment">// 当同一个接口有多个实现类Bean，@Qualifier指定要用Bean。</span></span><br><span class="line">    <span class="comment">// 或者不用@Qualifier，使用变量名用对应Bean的名。</span></span><br><span class="line">    <span class="meta">@Qualifier(value = &quot;userServiceImpl&quot;)</span></span><br><span class="line">    <span class="keyword">private</span> UserService userService;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span>  <span class="title function_">show</span><span class="params">()</span>&#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">show</span> <span class="operator">=</span> userService.show();</span><br><span class="line">        System.out.println(<span class="string">&quot;show:&quot;</span>+show);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>


<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 等效于@Autowired  @Qualifier(value = &quot;userServiceImpl&quot;)</span></span><br><span class="line"><span class="meta">@Resource(name = &quot;userServiceImpl&quot;)</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<blockquote>
<p>使用**@Resource**主要在新版本17需要导入一个注解</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&lt;!-- jsr-<span class="number">250</span>注解 Java提供的注解， spring提供了一个 <span class="meta">@Resource</span>  --&gt;</span><br><span class="line">&lt;dependency&gt;</span><br><span class="line">    &lt;groupId&gt;jakarta.annotation&lt;/groupId&gt;</span><br><span class="line">    &lt;artifactId&gt;jakarta.annotation-api&lt;/artifactId&gt;</span><br><span class="line">    &lt;version&gt;<span class="number">2.1</span><span class="number">.1</span>&lt;/version&gt;</span><br><span class="line">&lt;/dependency&gt;</span><br></pre></td></tr></table></figure>
</blockquote>
<h4 id="Bean属性赋值-基本类型属性自动装配DI"><a href="#Bean属性赋值-基本类型属性自动装配DI" class="headerlink" title="Bean属性赋值: 基本类型属性自动装配DI"></a>Bean属性赋值: 基本类型属性自动装配DI</h4><p>@Value注解: 读取配置文件的变量</p>
<figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">@Component</span></span><br><span class="line"><span class="string">@PropertySource(&quot;jdbc.properties&quot;)</span> <span class="string">//读取对应的配置文件</span></span><br><span class="line"><span class="string">public</span> <span class="string">class</span> <span class="string">JavaBean</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="string">//</span> <span class="string">冒号后面为默认值admin</span></span><br><span class="line">    <span class="string">@Value(&quot;$</span>&#123;<span class="string">jdbc.root:admin</span>&#125;<span class="string">&quot;)</span></span><br><span class="line"><span class="string">    private String name;</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">    @Override</span></span><br><span class="line"><span class="string">    public String toString() &#123;</span></span><br><span class="line"><span class="string">        return &quot;</span><span class="string">JavaBean</span>&#123;<span class="string">&quot; +</span></span><br><span class="line"><span class="string">                &quot;</span><span class="string">name=&#x27;&quot;</span> <span class="string">+</span> <span class="string">name</span> <span class="string">+</span> <span class="string">&#x27;\&#x27;&#x27;</span> <span class="string">+</span></span><br><span class="line">                <span class="string">&#x27;&#125;&#x27;</span><span class="string">;</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="基于配置类方式管理Bean，完全注解开发"><a href="#基于配置类方式管理Bean，完全注解开发" class="headerlink" title="基于配置类方式管理Bean，完全注解开发"></a>基于配置类方式管理Bean，完全注解开发</h3><p>不使用XML文件，使用<strong>配置类+注解实现</strong></p>
<p>Ioc具体实现使用<strong>AnnotationConfigApplicationContext</strong>对象</p>
<p><img src="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231025143927507.png" alt="image-20231025143927507"></p>
<p><img src="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231025154616460.png" alt="image-20231025154616460"></p>
<h4 id="配置类"><a href="#配置类" class="headerlink" title="配置类"></a>配置类</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 扫描指定包使注解生效</span></span><br><span class="line"><span class="meta">@ComponentScan(&quot;org.example&quot;)</span></span><br><span class="line"><span class="comment">// 表明该类是一个配置类：替代料原来的XML配置文件</span></span><br><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="comment">// 引入配置文件</span></span><br><span class="line"><span class="meta">@PropertySource(&quot;classpath:jdbc.properties&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UserConfig</span> &#123;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="Bean的细节"><a href="#Bean的细节" class="headerlink" title="@Bean的细节"></a>@Bean的细节</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">// 扫描指定包使注解生效</span></span><br><span class="line"><span class="meta">@ComponentScan(&quot;org.example&quot;)</span></span><br><span class="line"><span class="comment">// 表明该类是一个配置类：替代料原来的XML配置文件</span></span><br><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="comment">// 引入配置文件</span></span><br><span class="line"><span class="meta">@PropertySource(&quot;classpath:jdbc.properties&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UserConfig</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * &lt;bean -》 一个方法</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * 方法的返回值类型 == bean组件的类型或者他的接口和父类</span></span><br><span class="line"><span class="comment">     * 方法的名字 = bean id</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * 方法体可以自定义实现过程即可！</span></span><br><span class="line"><span class="comment">     * 最重要一步： <span class="doctag">@Bean</span> 会真正让配置类的方法创建的组件存储到ioc容器！！</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * 问题1： beanName的问题</span></span><br><span class="line"><span class="comment">     *         默认： 方法名</span></span><br><span class="line"><span class="comment">     *         指定：  name / value属性起名字，覆盖方法名</span></span><br><span class="line"><span class="comment">     * 问题2： 周期方法如何指定</span></span><br><span class="line"><span class="comment">     *        原有注解方案： PostConstruct + PreDestroy 注解指定</span></span><br><span class="line"><span class="comment">     *        bean属性指定： initMethod  / destroyMethod指定</span></span><br><span class="line"><span class="comment">     * 问题3： 作用域</span></span><br><span class="line"><span class="comment">     *         和以前还是一样<span class="doctag">@Scope</span>注解，默认是单例</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * 问题4： 如何引用其他的ioc组件</span></span><br><span class="line"><span class="comment">     *         直接调用对方的bean方法即可</span></span><br><span class="line"><span class="comment">     *         直接形参变量进行引入，要求必须有对应的组件，如果有多个，形参名 = 组件id标识即可</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Bean(&quot;指定Bean的id&quot;)</span></span><br><span class="line">    <span class="comment">//指定作用域，默认为单例</span></span><br><span class="line">    <span class="meta">@Scope</span></span><br><span class="line">    <span class="keyword">public</span> JavaBean <span class="title function_">javaBean</span><span class="params">()</span>&#123;</span><br><span class="line">        <span class="type">JavaBean</span> <span class="variable">javaBean</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">JavaBean</span>();</span><br><span class="line">        <span class="keyword">return</span> javaBean;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 方案一：如果其它组件也是@Bean，例如：可以直接调用javaBea()</span></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="keyword">public</span> JavaBeanService <span class="title function_">javaBeanService</span><span class="params">()</span>&#123;</span><br><span class="line">        <span class="type">JavaBeanService</span> <span class="variable">javaBeanService</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">JavaBeanService</span>();</span><br><span class="line">        <span class="comment">// 引用其它Bean组件</span></span><br><span class="line">        <span class="comment">// 方案一：如果其它组件也是@Bean，例如：可以直接调用javaBean()</span></span><br><span class="line">        javaBeanService.show(javaBean());</span><br><span class="line">        <span class="keyword">return</span> javaBeanService;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 方案二：形参列表指定要用的组件类型，自动装配，例如：JavaBean javaBean</span></span><br><span class="line">    <span class="comment">//        如果有多个，形参名等于对应的额Bean的id</span></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="keyword">public</span> JavaBeanService <span class="title function_">javaBeanService1</span><span class="params">(JavaBean javaBean)</span>&#123;</span><br><span class="line">        <span class="type">JavaBeanService</span> <span class="variable">javaBeanService</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">JavaBeanService</span>();</span><br><span class="line">        javaBeanService.show(javaBean);</span><br><span class="line">        <span class="keyword">return</span> javaBeanService;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="Import"><a href="#Import" class="headerlink" title="@Import"></a>@Import</h4><p>把多个配置类放在一起</p>
<h3 id="整合Spring-Test搭建测试环境"><a href="#整合Spring-Test搭建测试环境" class="headerlink" title="整合Spring+Test搭建测试环境"></a>整合Spring+Test搭建测试环境</h3><p>**@SpringJUnitConfig: 在测试类中不用指定XmlApplicationContext对象 **</p>
<p>优点：</p>
<ol>
<li>不需要自己创建<strong>IOC容器对象</strong></li>
<li>任何<strong>需要的Bean</strong>都可以在测试类中享受<strong>自动装配</strong></li>
</ol>
<p>依赖：</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&lt;dependency&gt;</span></span><br><span class="line">             <span class="string">&lt;groupId&gt;org.junit.jupiter&lt;/groupId&gt;</span></span><br><span class="line">             <span class="string">&lt;artifactId&gt;junit-jupiter-api&lt;/artifactId&gt;</span></span><br><span class="line">             <span class="string">&lt;version&gt;5.3.1&lt;/version&gt;</span></span><br><span class="line">         <span class="string">&lt;/dependency&gt;</span></span><br><span class="line"><span class="string">&lt;dependency&gt;</span></span><br><span class="line">             <span class="string">&lt;groupId&gt;org.springframework&lt;/groupId&gt;</span></span><br><span class="line">             <span class="string">&lt;artifactId&gt;spring-test&lt;/artifactId&gt;</span></span><br><span class="line">             <span class="string">&lt;version&gt;6.0.6&lt;/version&gt;</span></span><br><span class="line">             <span class="string">&lt;scope&gt;test&lt;/scope&gt;</span></span><br><span class="line">         <span class="string">&lt;/dependency&gt;</span></span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//@SpringJUnitConfig(location= 指定配置文件，value指定配置类)</span></span><br><span class="line"><span class="meta">@SpringJUnitConfig(value = UserConfig.class)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Test1</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> JavaBean javaBean;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span>  <span class="title function_">getBean</span><span class="params">()</span>&#123;</span><br><span class="line">        <span class="comment">// 在Junit中直接使用@SpringJUnitConfig绑定配置类或配置文件</span></span><br><span class="line">        System.out.println(javaBean);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="四、SpringAOP"><a href="#四、SpringAOP" class="headerlink" title="四、SpringAOP"></a>四、SpringAOP</h2><p>提取<strong>重复附加功能代码</strong>到一个类中，可以通过<strong>代理实现</strong>。</p>
<h3 id="代理模式"><a href="#代理模式" class="headerlink" title="代理模式"></a>代理模式</h3><p><span style="color:red"><strong>代理方式可以解决附加功能代码干扰核心代码和不方便统一管理的问题。</strong></span></p>
<p>通过一个代理类，让我们在<strong>调用目标方法</strong>的时候，<strong>不再直接对目标方法进行调用</strong>，而是通过<strong>代理类间接调用</strong>。让不属于目标方法核心逻辑的代码从目标方法中剥离除了—-<strong>解耦</strong>。调用目标方法时先调用代理对象的方法，<strong>减少对目标方法的调用和打扰</strong>，同时让附加功能能够集中到一起有利于维护。</p>
<p><img src="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231026212602884.png" alt="image-20231026212602884"></p>
<p>代理：</p>
<p><strong>静态代理：</strong>自己创建代理类</p>
<p><strong>动态代理</strong>：动态创建代理类</p>
<p> &#x3D;&#x3D;开发中用SpringAOP实现&#x3D;&#x3D;</p>
<p>&#x3D;&#x3D;静态代理&#x3D;&#x3D;</p>
<p><strong>缺点：</strong>静态代理确实解耦，但代码写死了，不具备灵活性，多个目标需要多个代理类，产生大量重复代码。</p>
<blockquote>
<p>Calculator类</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">Calculator</span> &#123;</span><br><span class="line">    <span class="type">int</span> <span class="title function_">add</span><span class="params">(<span class="type">int</span> i,<span class="type">int</span> j)</span>;</span><br><span class="line">    <span class="type">int</span> <span class="title function_">sub</span><span class="params">(<span class="type">int</span> i,<span class="type">int</span> j)</span>;</span><br><span class="line">    <span class="type">int</span> <span class="title function_">mul</span><span class="params">(<span class="type">int</span> i, <span class="type">int</span> j)</span>;</span><br><span class="line">    <span class="type">int</span> <span class="title function_">div</span><span class="params">(<span class="type">int</span> i,<span class="type">int</span> j)</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<blockquote>
<p>CalculatorPureImpl类</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CalculatorPureImpl</span> <span class="keyword">implements</span> <span class="title class_">Calculator</span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">add</span><span class="params">(<span class="type">int</span> i, <span class="type">int</span> j)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> i+j;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">sub</span><span class="params">(<span class="type">int</span> i, <span class="type">int</span> j)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> i-j;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">mul</span><span class="params">(<span class="type">int</span> i, <span class="type">int</span> j)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> i*j;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">div</span><span class="params">(<span class="type">int</span> i, <span class="type">int</span> j)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> i/j;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<blockquote>
<p>StaticProxyCalculator类</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">StaticProxyCalculator</span> <span class="keyword">implements</span> <span class="title class_">Calculator</span>&#123;</span><br><span class="line">    <span class="comment">// 将代理的目标对象声明为成员变量</span></span><br><span class="line">    <span class="keyword">private</span> Calculator target;</span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">StaticProxyCalculator</span><span class="params">(Calculator target)</span>&#123;</span><br><span class="line">        <span class="built_in">this</span>.target=target;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">add</span><span class="params">(<span class="type">int</span> i, <span class="type">int</span> j)</span> &#123;</span><br><span class="line">        <span class="comment">// 附加功能由代理类中的代理方法实现</span></span><br><span class="line">        System.out.println(<span class="string">&quot;i=&quot;</span>+i+<span class="string">&quot;,j=&quot;</span>+j);</span><br><span class="line">        <span class="comment">// 核心业务（调用目标）</span></span><br><span class="line">        <span class="type">int</span> <span class="variable">add</span> <span class="operator">=</span> target.add(i, j);</span><br><span class="line">        <span class="keyword">return</span> add;</span><br><span class="line">    &#125;</span><br><span class="line">   ......</span><br><span class="line">       </span><br></pre></td></tr></table></figure>

<blockquote>
<p>测试</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Main</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">// 房东 目标</span></span><br><span class="line">        <span class="type">Calculator</span> <span class="variable">target</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">CalculatorPureImpl</span>();</span><br><span class="line"></span><br><span class="line">        <span class="comment">//中介  代理</span></span><br><span class="line">        <span class="type">Calculator</span> <span class="variable">proxy</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">StaticProxyCalculator</span>(target);</span><br><span class="line"></span><br><span class="line">        <span class="type">int</span> <span class="variable">add</span> <span class="operator">=</span> proxy.add(<span class="number">1</span>, <span class="number">1</span>);</span><br><span class="line">        System.out.println(<span class="string">&quot;add:&quot;</span> + add);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="动态代理"><a href="#动态代理" class="headerlink" title="动态代理"></a>动态代理</h3><ul>
<li>JDK动态代理（<strong>了解</strong>）：JDK原生方式，需要<strong>被代理的目标类必须实现接口</strong>。根据目标类的接口动态生成一个代理对象，<strong>代理对象和目标类有相同的接口</strong></li>
<li>cglib代理（Spring）：通过<strong>继承被代理的目标类实现代理</strong>，<strong>不需要目标类实现接口</strong>。</li>
</ul>
<blockquote>
<p>JDK动态代理</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ProxyFactory</span> &#123;</span><br><span class="line">    <span class="comment">//目标类对象</span></span><br><span class="line">    <span class="keyword">private</span> Object target;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">ProxyFactory</span><span class="params">(Object target)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.target = target;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//通过该方法来产出代理类</span></span><br><span class="line">    <span class="keyword">public</span> Object <span class="title function_">getProxy</span><span class="params">()</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="comment">/**</span></span><br><span class="line"><span class="comment">         * ClassLoader loader；类加载器，将生成的代理类加载到内存</span></span><br><span class="line"><span class="comment">         * 三种类加载器：</span></span><br><span class="line"><span class="comment">         * 根类加载器：主要是加载核心类库，底层是由C来实现的</span></span><br><span class="line"><span class="comment">         * 扩展类加载器：主要加载的是扩展类库</span></span><br><span class="line"><span class="comment">         * 应用类加载器：加载第三方类库和自定义类</span></span><br><span class="line"><span class="comment">         * Class[] interfaces:目标类实现的接口</span></span><br><span class="line"><span class="comment">         * InvocationHandler:设置代理类如何实现目标类接口所定义的方法</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line">        <span class="comment">//获取应用类加载器</span></span><br><span class="line">        <span class="type">ClassLoader</span> <span class="variable">classLoader</span> <span class="operator">=</span> <span class="built_in">this</span>.getClass().getClassLoader();</span><br><span class="line">        <span class="comment">//获得目标类实现的接口</span></span><br><span class="line">        Class&lt;?&gt;[] interfaces = target.getClass().getInterfaces();</span><br><span class="line">        InvocationHandler h=<span class="keyword">new</span> <span class="title class_">InvocationHandler</span>() &#123;</span><br><span class="line">            <span class="comment">//invoke表示代理类中的方法的执行</span></span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="keyword">public</span> Object <span class="title function_">invoke</span><span class="params">(Object proxy, Method method, Object[] args)</span> <span class="keyword">throws</span> Throwable &#123;</span><br><span class="line">                <span class="comment">//proxy表示代理类对象，method表示要执行的方法，args表示要执行的方法的参数列表</span></span><br><span class="line">                System.out.println(<span class="string">&quot;要增强的业务代码。。。。&quot;</span>);</span><br><span class="line">                <span class="comment">//在代理类中执行目标类的方法，核心业务</span></span><br><span class="line">                <span class="type">Object</span> <span class="variable">result</span> <span class="operator">=</span> method.invoke(target, args);</span><br><span class="line">                System.out.println(<span class="string">&quot;要增强的业务代码。。。。。&quot;</span>);</span><br><span class="line">                <span class="keyword">return</span> result;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;;</span><br><span class="line">        <span class="keyword">return</span> Proxy.newProxyInstance(classLoader,interfaces,h);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">    <span class="comment">// 房东</span></span><br><span class="line">    <span class="type">CalculatorPureImpl</span> <span class="variable">target</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">CalculatorPureImpl</span>();</span><br><span class="line">    <span class="comment">//jdk代理</span></span><br><span class="line">    <span class="type">ProxyFactory</span> <span class="variable">proxyFactory</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ProxyFactory</span>(target);</span><br><span class="line">    <span class="comment">//类型要用接口,因为返回的代理对象（目标接口的另一个实现）</span></span><br><span class="line">    <span class="type">Calculator</span> <span class="variable">proxy</span> <span class="operator">=</span> (Calculator) proxyFactory.getProxy();</span><br><span class="line">    proxy.add(<span class="number">1</span>,<span class="number">1</span>);</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="面向切面编程（AOP）"><a href="#面向切面编程（AOP）" class="headerlink" title="面向切面编程（AOP）"></a>面向切面编程（AOP）</h3><p>AOP是面向对象编程（OOP）的补充和完善。</p>
<p><img src="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231027085356334.png" alt="image-20231027085356334"></p>
<p>OOP是纵向的，父类、子类、子子类，之间通过继承，实现纵向发展。</p>
<p>&#x3D;&#x3D;AOP是对OOP（面向对象编程）的补充，AOP是面向切面编程，横向的编程思维，将代码中重复的非核心业务代码提取到一个公共模块（Aspect，切面）。最终用动态代理技术实现横向插入到各个方法中。&#x3D;&#x3D;</p>
<blockquote>
<p>AOP应用场景</p>
</blockquote>
<ol>
<li>日志</li>
<li>事务处理</li>
<li>安全控制</li>
<li>异常处理</li>
</ol>
<blockquote>
<p>AOP术语</p>
</blockquote>
<ol>
<li><p>横切关注点：<strong>要提取的非核心业务</strong>，经常发生在<strong>核心关注点</strong>（核心业务逻辑）的多处，例如，权限认证、日志、事务等</p>
</li>
<li><p>通知（增强）：每个横切关注点要做的事务都需要写一个方法来实现，这个就叫通知方法</p>
</li>
</ol>
<p>​		前置通知：在被代理的目标方法前执行</p>
<p>​		返回通知：在被代理的目标方法成功结束后执行（<strong>成功才会调用</strong>）</p>
<p>​		异常通知</p>
<p>​		后置通知：在被代理的目标方法最终结束后执行（<strong>一定会被调用</strong>）	</p>
<p>​		环绕通知：使用try-catch围绕整个被代理的目标方法。</p>
<ol start="3">
<li><p>连接点：可以被切入的方法</p>
</li>
<li><p>切入点：被选中的连接点</p>
</li>
<li><p><strong>切面Aspect</strong>：切入点和通知的结合，是一个类</p>
</li>
<li><p>织入weave:  <strong>把通知应用到目标上</strong>，<strong>Spring在运行期间织入</strong></p>
</li>
</ol>
<p><img src="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231027092230348.png" alt="image-20231027092230348"></p>
<h3 id="基于注解实现AOP"><a href="#基于注解实现AOP" class="headerlink" title="基于注解实现AOP"></a>基于注解实现AOP</h3><p>&#x3D;&#x3D;AOP只针对IOC容器的对象创建代理，将代理对象存储到IOC容器中。&#x3D;&#x3D;</p>
<h4 id="底层技术组成"><a href="#底层技术组成" class="headerlink" title="底层技术组成"></a>底层技术组成</h4><p><img src="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231027095757104.png" alt="image-20231027095757104"></p>
<p>AspectJ:早期的AOP实现框架，SpringAOP借用了AspectJ中AOP注解</p>
<blockquote>
<p>依赖导入</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&lt;dependency&gt;</span><br><span class="line">          &lt;groupId&gt;org.springframework&lt;/groupId&gt;</span><br><span class="line">          &lt;artifactId&gt;spring-aspects&lt;/artifactId&gt;</span><br><span class="line">          &lt;version&gt;<span class="number">6.0</span><span class="number">.6</span>&lt;/version&gt;</span><br><span class="line">      &lt;/dependency&gt;</span><br></pre></td></tr></table></figure>

<blockquote>
<p>接口实现类—-<strong>也要放到IOC容器中，因为AOP只针对IOC容器中的对象</strong></p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CalculatorPureImpl</span> <span class="keyword">implements</span> <span class="title class_">Calculator</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">add</span><span class="params">(<span class="type">int</span> i, <span class="type">int</span> j)</span> &#123;</span><br><span class="line">        <span class="type">int</span> <span class="variable">result</span> <span class="operator">=</span> i + j;</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">sub</span><span class="params">(<span class="type">int</span> i, <span class="type">int</span> j)</span> &#123;</span><br><span class="line">        <span class="type">int</span> <span class="variable">result</span> <span class="operator">=</span> i - j;</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">mul</span><span class="params">(<span class="type">int</span> i, <span class="type">int</span> j)</span> &#123;</span><br><span class="line">        <span class="type">int</span> <span class="variable">result</span> <span class="operator">=</span> i * j;</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">div</span><span class="params">(<span class="type">int</span> i, <span class="type">int</span> j)</span> &#123;</span><br><span class="line">        <span class="type">int</span> <span class="variable">result</span> <span class="operator">=</span> i / j;</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<blockquote>
<p>切面类</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 1. 定义方法存储增强代码，具体插入几个方法，根据插入位置决定</span></span><br><span class="line"><span class="comment"> * 2. 使用注解配置，指定插入位置</span></span><br><span class="line"><span class="comment"> * 前置：<span class="doctag">@Before</span></span></span><br><span class="line"><span class="comment"> * 后置：<span class="doctag">@AfterReturning</span></span></span><br><span class="line"><span class="comment"> * 异常：<span class="doctag">@AfterThrowing</span></span></span><br><span class="line"><span class="comment"> * 最后：<span class="doctag">@After</span></span></span><br><span class="line"><span class="comment"> * 环绕：<span class="doctag">@Around</span></span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * try&#123;</span></span><br><span class="line"><span class="comment"> *     前置</span></span><br><span class="line"><span class="comment"> *     目标方法</span></span><br><span class="line"><span class="comment"> *     后置</span></span><br><span class="line"><span class="comment"> * &#125;catch()&#123;</span></span><br><span class="line"><span class="comment"> *     异常</span></span><br><span class="line"><span class="comment"> * &#125;finally&#123;</span></span><br><span class="line"><span class="comment"> *     最后</span></span><br><span class="line"><span class="comment"> * &#125;</span></span><br><span class="line"><span class="comment"> * 3. 配置切点表达式（选中切入的方法，切点）</span></span><br><span class="line"><span class="comment"> * 4. 添加<span class="doctag">@Component</span>和<span class="doctag">@Aspect</span>注解</span></span><br><span class="line"><span class="comment"> * 5. 在配置文件中开启aspect注解的支持  <span class="doctag">@EnableAspectJAutoProxy</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@Aspect</span> <span class="comment">// 切面</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">LogAdvice</span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Before(&quot;execution(* com.atguigu.service.*.*(..))&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">start</span><span class="params">()</span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;方法开始了&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@After(&quot;execution(* com.atguigu.service.*.*(..))&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">after</span><span class="params">()</span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;方法结束了&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@AfterThrowing(&quot;execution(* com.atguigu.service.*.*(..))&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">error</span><span class="params">()</span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;方法报错了&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<blockquote>
<p>配置类</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@ComponentScan(&quot;com.atguigu&quot;)</span></span><br><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="meta">@EnableAspectJAutoProxy</span> <span class="comment">//开启aspect注解支持</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">config</span> &#123;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<blockquote>
<p>测试</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@SpringJUnitConfig(value = config.class)</span>  <span class="comment">// 加载配置文件并创建IOC容器</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SpringAop</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Calculator必须用接口，不能用实现类，</span></span><br><span class="line">    <span class="comment">// JDK代理对象是根据同一个接口实现的，不能用实现同一个接口的另一个实现类</span></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> Calculator calculator;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="type">int</span> <span class="variable">add</span> <span class="operator">=</span> calculator.div(<span class="number">1</span>, <span class="number">0</span>);</span><br><span class="line">        System.out.printf(<span class="string">&quot;add:&quot;</span> + add);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="获取目标方法（切点）信息"><a href="#获取目标方法（切点）信息" class="headerlink" title="获取目标方法（切点）信息"></a>获取目标方法（切点）信息</h4><p><strong>获取目标方法信息，确定是哪一个目标方法。</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 增强方法获取目标方法信息</span></span><br><span class="line"><span class="comment"> * 1. 全部增强方法，获取目标方法的信息（JoinPoint）（方法名、参数、访问修饰符）</span></span><br><span class="line"><span class="comment"> * 2. 返回的结果   <span class="doctag">@AfterReturning</span></span></span><br><span class="line"><span class="comment"> *       <span class="doctag">@AfterReturning</span>(value = &quot;execution(* com.atguigu.service.*.*(..))&quot;,returning = &quot;result&quot;)</span></span><br><span class="line"><span class="comment"> *      参数列表指定返回结果绑定到Object result</span></span><br><span class="line"><span class="comment"> * 3. 异常信息   <span class="doctag">@AfterThrowing</span></span></span><br><span class="line"><span class="comment"> *      和上面类似 Throwable e接收</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@Aspect</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyAdivce</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Before(&quot;execution(* com.atguigu.service.*.*(..))&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">before</span><span class="params">(JoinPoint joinPoint)</span>&#123;</span><br><span class="line">        <span class="comment">/**JoinPoint连接点，目标方法信息的封装对象</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line">        <span class="comment">//1. 获取方法属于类的信息</span></span><br><span class="line">        <span class="type">String</span> <span class="variable">simpleName</span> <span class="operator">=</span> joinPoint.getTarget().getClass().getSimpleName();</span><br><span class="line">        <span class="comment">//2. 获取方法名</span></span><br><span class="line">        <span class="type">String</span> <span class="variable">methodName</span> <span class="operator">=</span> joinPoint.getSignature().getName();</span><br><span class="line">        <span class="comment">//3. 获取目标方法参数列表</span></span><br><span class="line">        Object[] args = joinPoint.getArgs();</span><br><span class="line">        System.out.println(<span class="string">&quot;方法名：&quot;</span>+methodName);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@AfterReturning(value = &quot;execution(* com.atguigu.service.*.*(..))&quot;,returning = &quot;result&quot;)</span> <span class="comment">//正常返回</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">afterReturning</span><span class="params">(JoinPoint joinPoint,Object result)</span>&#123;</span><br><span class="line">        <span class="comment">// returning = &quot;result&quot;指定接收方法的返回结果</span></span><br><span class="line">        System.out.println(<span class="string">&quot;返回结果：&quot;</span>+result);</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@After(&quot;execution(* com.atguigu.service.*.*(..))&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">after</span><span class="params">(JoinPoint joinPoint)</span>&#123;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@AfterThrowing(value = &quot;execution(* com.atguigu.service.*.*(..))&quot;,throwing = &quot;e&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">afterThrowing</span><span class="params">(JoinPoint joinPoint,Throwable e)</span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;异常信息&quot;</span>+e);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="切点表达式"><a href="#切点表达式" class="headerlink" title="切点表达式"></a>切点表达式</h4><p>指定切点的语言，通过匹配规则，指定需要被切入的目标对象</p>
<p><img src="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231027133557662.png" alt="image-20231027133557662"></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * TODO 切点表达式</span></span><br><span class="line"><span class="comment"> * 固定语法execution(1,2,3.4.5(6))</span></span><br><span class="line"><span class="comment"> * 1. 访问修饰符 public /private</span></span><br><span class="line"><span class="comment"> * 2. 返回值类型 String /int void</span></span><br><span class="line"><span class="comment"> * 如果不考虑访问修饰符和返回值，这两位合成一起写为 *</span></span><br><span class="line"><span class="comment"> * 3. 包的位置</span></span><br><span class="line"><span class="comment"> *    具体的包：com.example.impl</span></span><br><span class="line"><span class="comment"> *    com.example.impl.* 表示impl下的所有包</span></span><br><span class="line"><span class="comment"> *    com..impl  表示中间是任意层</span></span><br><span class="line"><span class="comment">   4. 类的名称</span></span><br><span class="line"><span class="comment">      *表示任何类</span></span><br><span class="line"><span class="comment"> *    *impl 表示以impl结尾的类名</span></span><br><span class="line"><span class="comment"> * 5. 方法名</span></span><br><span class="line"><span class="comment"> * 6. 参数列表</span></span><br><span class="line"><span class="comment"> *    没有参数（）</span></span><br><span class="line"><span class="comment"> *    有具体参数（String）</span></span><br><span class="line"><span class="comment"> *    任意参数（..）</span></span><br><span class="line"><span class="comment"> *    (String..) 第一个参数为String，后面随意</span></span><br><span class="line"><span class="comment"> */</span></span><br></pre></td></tr></table></figure>

<h4 id="重用切点表达式"><a href="#重用切点表达式" class="headerlink" title="重用切点表达式"></a>重用切点表达式</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 切点表达式的提取和复用</span></span><br><span class="line"><span class="comment"> * 1. 当前类提取切点表达式</span></span><br><span class="line"><span class="comment"> *     <span class="doctag">@Pointcut</span>(&quot;execution(* com.atguigu.service.*.*(..))&quot;)</span></span><br><span class="line"><span class="comment"> *     public void pc()&#123;&#125;</span></span><br><span class="line"><span class="comment"> *     在需要用的地方，直接用方法</span></span><br><span class="line"><span class="comment"> *     <span class="doctag">@After</span>(&quot;pc()&quot;)</span></span><br><span class="line"><span class="comment"> * 2. 创建一个存储切点的类，单独维护切点</span></span><br><span class="line"><span class="comment"> *      调用时，需要类的全限定符</span></span><br><span class="line"><span class="comment"> *      <span class="doctag">@After</span>(&quot;com.atguigu.aop.MyPointCut.pc()&quot;)</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> */</span></span><br></pre></td></tr></table></figure>

<blockquote>
<p>储存切点类</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyPointCut</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Pointcut(&quot;execution(* com.atguigu.service.*.*(..))&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">pc</span><span class="params">()</span> &#123;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Pointcut(&quot;execution(* com..service.*.*(..))&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">pc1</span><span class="params">()</span> &#123;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h4 id="环绕通知-更推荐分开写，而不是环绕通知"><a href="#环绕通知-更推荐分开写，而不是环绕通知" class="headerlink" title="环绕通知(更推荐分开写，而不是环绕通知)"></a>环绕通知(更推荐分开写，而不是环绕通知)</h4><p>允许自定义插入位置</p>
<p><strong>同一个切面采用环绕通知写：</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@Aspect</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TxAroundAdvice</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/** 环绕通知需要在通知中，定义目标方法的执行</span></span><br><span class="line"><span class="comment">     * JoinPoint joinPoint：只能获取目标方法信息，不能执行</span></span><br><span class="line"><span class="comment">     * ProceedingJoinPoint joinPoint：获取目标方法信息和执行</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * Return 是目标方法的返回值</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Around(&quot;com.atguigu.aop.MyPointCut.pc()&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> Object <span class="title function_">trascatioin</span><span class="params">(ProceedingJoinPoint joinPoint)</span>&#123;</span><br><span class="line"></span><br><span class="line">        Object result=<span class="literal">null</span>;</span><br><span class="line">        <span class="comment">// 方法参数列表</span></span><br><span class="line">        Object[] args=joinPoint.getArgs();</span><br><span class="line">        <span class="comment">//保证目标方法被执行</span></span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;开启事务&quot;</span>);</span><br><span class="line">            result = joinPoint.proceed(args);</span><br><span class="line">            System.out.println(<span class="string">&quot;结束事务&quot;</span>);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Throwable e) &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;事务回滚&quot;</span>);</span><br><span class="line">            <span class="comment">// 必须抛出异常</span></span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">RuntimeException</span>(e);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><strong>同一个切面采用分开写：</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@Aspect</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TxAdvice</span> &#123;</span><br><span class="line">    <span class="meta">@After(&quot;com.atguigu.aop.MyPointCut.pc()&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">begin</span><span class="params">()</span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;开启事务&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@AfterReturning(&quot;com.atguigu.aop.MyPointCut.pc()&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">commit</span><span class="params">()</span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;提交事务&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@AfterThrowing(&quot;com.atguigu.aop.MyPointCut.pc()&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">rollback</span><span class="params">()</span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;回滚事务&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="切面优先级设置"><a href="#切面优先级设置" class="headerlink" title="切面优先级设置"></a>切面优先级设置</h4><p> 在目标方法有多个切面时，按照优先级顺序执行。</p>
<p><strong>使用@Order（较小的数）：优先级高</strong></p>
<p> <img src="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231027141324103.png" alt="image-20231027141324103"></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//在切面类上添加@Order注解</span></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@Aspect</span></span><br><span class="line"><span class="meta">@Order(11)</span> <span class="comment">//设置优先级，越小优先级越高</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">LogAdvice</span>&#123;</span><br></pre></td></tr></table></figure>

<h4 id="Cglib动态代理生效"><a href="#Cglib动态代理生效" class="headerlink" title="Cglib动态代理生效"></a>Cglib动态代理生效</h4><p>目标对象的实现类，删除实现</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">删除 <span class="keyword">implements</span> <span class="title class_">Calculator</span></span><br></pre></td></tr></table></figure>

<p>并且在自动装配目标实现类，采用实现类类型，而不是接口。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Autowired</span></span><br><span class="line"><span class="keyword">private</span> CalculatorPureImpl calculator;</span><br></pre></td></tr></table></figure>

<h4 id="AOP注解总结"><a href="#AOP注解总结" class="headerlink" title="AOP注解总结"></a>AOP注解总结</h4><p><img src="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231027185441163.png" alt="image-20231027185441163"></p>
<p><img src="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231027190507813.png" alt="image-20231027190507813"></p>
<p>&#x3D;&#x3D;应用切面后，真正放在IOC容器的是代理类的对象&#x3D;&#x3D;</p>
<p>&#x3D;&#x3D;目标类并没有放到IOC容器中，所以根据目标类的类型从IOC容器找不到&#x3D;&#x3D;</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CalculatorPureImpl</span> <span class="keyword">implements</span> <span class="title class_">Calculator</span> &#123;</span><br></pre></td></tr></table></figure>

<h2 id="五、Spring声明式事务"><a href="#五、Spring声明式事务" class="headerlink" title="五、Spring声明式事务"></a>五、Spring声明式事务</h2><ul>
<li>编程式事务：通过手动编写程序管理事务，即<strong>通过代码的方式直接控制事务的提交和回滚</strong>。通常使用<strong>PlatformTransactionManager</strong>实现编程式事务。可以按照自己的需求控制事务的粒度、模式等。但是冗余度高，代码复用度低、麻烦。</li>
</ul>
<p>​	<img src="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231027191230876.png" alt="image-20231027191230876"></p>
<ul>
<li>声明式事务：<strong>通过注解控制事务的提交和回滚</strong>。</li>
</ul>
<blockquote>
<p>区别：</p>
</blockquote>
<ol>
<li>编程式事务需要手动编写代码管理事务</li>
<li>声明式事务通过配置文件或注解控制事务</li>
</ol>
<h3 id="声明式事务"><a href="#声明式事务" class="headerlink" title="声明式事务"></a>声明式事务</h3><p>Spring-tx是AOP的进一步封装。</p>
<p><img src="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231027191626944.png" alt="image-20231027191626944"></p>
<h3 id="Spring事务管理器"><a href="#Spring事务管理器" class="headerlink" title="Spring事务管理器"></a>Spring事务管理器</h3><blockquote>
<p>声明式事务对应依赖</p>
</blockquote>
<ul>
<li><strong>spring-tx:</strong> 包含声明式事务实现的基本规范（事务管理器接口和增强）</li>
<li><strong>spring-jdbc:</strong> 包含对Datasource方式事务管理器实现类DataSourceTransactionManager</li>
<li><strong>spring-orm:</strong> 包含其它持久层框架的事务管理器实现类：如hibernate&#x2F;jpa等</li>
</ul>
<p><img src="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231027192121789.png" alt="image-20231027192121789"></p>
<p>我们现在要使用的事务管理器是org.springframework.jdbc.datasource.<strong>DataSourceTransactionManager</strong>，将来<strong>整合JDBC方式、JdbcTemplate方式、 Mybatis方式</strong>的事务实现!</p>
<p>DataSourceTransactionIvanager类中的主要方法:</p>
<p>doBegin():开启事务<br>doSuspend():挂起事务</p>
<p>doResume(:恢复挂起的事务</p>
<p>docommit():提交事务</p>
<p>doRollback():回滚事务</p>
<h4 id="基于注解的声明式事务"><a href="#基于注解的声明式事务" class="headerlink" title="基于注解的声明式事务"></a>基于注解的声明式事务</h4><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&lt;dependency&gt;</span></span><br><span class="line">            <span class="string">&lt;groupId&gt;org.springframework&lt;/groupId&gt;</span></span><br><span class="line">            <span class="string">&lt;artifactId&gt;spring-jdbc&lt;/artifactId&gt;</span></span><br><span class="line">            <span class="string">&lt;version&gt;6.0.6&lt;/version&gt;</span></span><br><span class="line">        <span class="string">&lt;/dependency&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="string">&lt;dependency&gt;</span></span><br><span class="line">            <span class="string">&lt;groupId&gt;org.springframework&lt;/groupId&gt;</span></span><br><span class="line">            <span class="string">&lt;artifactId&gt;spring-tx&lt;/artifactId&gt;</span></span><br><span class="line">            <span class="string">&lt;version&gt;6.0.6&lt;/version&gt;</span></span><br><span class="line">        <span class="string">&lt;/dependency&gt;</span></span><br><span class="line">        </span><br><span class="line">        <span class="string">&lt;dependency&gt;</span></span><br><span class="line">            <span class="string">&lt;groupId&gt;mysql&lt;/groupId&gt;</span></span><br><span class="line">            <span class="string">&lt;artifactId&gt;mysql-connector-java&lt;/artifactId&gt;</span></span><br><span class="line">            <span class="string">&lt;version&gt;8.0.25&lt;/version&gt;</span></span><br><span class="line">        <span class="string">&lt;/dependency&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="string">&lt;dependency&gt;</span></span><br><span class="line">            <span class="string">&lt;groupId&gt;com.alibaba&lt;/groupId&gt;</span></span><br><span class="line">            <span class="string">&lt;artifactId&gt;druid&lt;/artifactId&gt;</span></span><br><span class="line">            <span class="string">&lt;version&gt;1.2.8&lt;/version&gt;</span></span><br><span class="line">        <span class="string">&lt;/dependency&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="基本事务控制"><a href="#基本事务控制" class="headerlink" title="基本事务控制"></a>基本事务控制</h4><blockquote>
<p><strong>配置类</strong></p>
</blockquote>
<ol>
<li><strong>选择对应的事务管理器实现加入到IOC容器中</strong></li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Bean</span></span><br><span class="line">    <span class="keyword">public</span> TransactionManager <span class="title function_">transactionManager</span><span class="params">(DataSource dataSource)</span>&#123;</span><br><span class="line">        <span class="comment">//内部要进行事务的操作，基于的连接池</span></span><br><span class="line">        <span class="type">DataSourceTransactionManager</span> <span class="variable">dataSourceTransactionManager</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">DataSourceTransactionManager</span>();</span><br><span class="line">        <span class="comment">//需要连接池对象</span></span><br><span class="line">        dataSourceTransactionManager.setDataSource(dataSource);</span><br><span class="line">        <span class="keyword">return</span> dataSourceTransactionManager;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<ol start="2">
<li>开启事务支持</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@EnableTransactionManagement</span> <span class="comment">//开启事务注解的支持</span></span><br></pre></td></tr></table></figure>

<blockquote>
<p><strong>方法添加事务和事务属性</strong></p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Transactional(timeout = 3)</span>  <span class="comment">// 超时时间</span></span><br><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">StudentService</span> &#123;</span><br><span class="line">    </span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> StudentDao studentDao;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 添加事务：</span></span><br><span class="line"><span class="comment">     *      <span class="doctag">@Transactional</span></span></span><br><span class="line"><span class="comment">     *      位置： 方法 | 类上</span></span><br><span class="line"><span class="comment">     *      方法： 当前方法有事务</span></span><br><span class="line"><span class="comment">     *      类上： 类下的所有方法都有事务</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * 1.只读模式</span></span><br><span class="line"><span class="comment">     *   只读模式可以提升查询事务的效率！ 推荐事务中只有查询代码，使用只读模式！</span></span><br><span class="line"><span class="comment">     *   默认： boolean readOnly() default false;</span></span><br><span class="line"><span class="comment">     *   解释： 一般情况下，都是通过类添加注解添加事务！</span></span><br><span class="line"><span class="comment">     *         类下的所有方法都有事务！</span></span><br><span class="line"><span class="comment">     *         查询方法可以通过再次添加注解，设置为只读模式，提高效率!</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * 2.超时时间</span></span><br><span class="line"><span class="comment">     *   默认： 永远不超时  -1</span></span><br><span class="line"><span class="comment">     *   设置 timeout = 时间 秒数  超过时间，就会回滚事务和释放异常！ TransactionTimedOutException</span></span><br><span class="line"><span class="comment">     *   如果类上设置事务属性，方法也设置了事务注解！ 方法会不会生效？？</span></span><br><span class="line"><span class="comment">     *   不会生效： 方法上的注解默认超时时间为-1，覆盖了类上的注解！</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * 3.指定异常回滚和指定异常不回滚：</span></span><br><span class="line"><span class="comment">     *   默认情况下，指定发生运行时异常事务才会回滚！</span></span><br><span class="line"><span class="comment">     *   我们可以指定Exception异常来控制所有异常都回滚！</span></span><br><span class="line"><span class="comment">     *   rollbackFor = Exception.class</span></span><br><span class="line"><span class="comment">     *   noRollbackFor = 回滚异常范围内，控制某个异常不回滚！</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * 4.隔离级别设置</span></span><br><span class="line"><span class="comment">     *   推荐设置第二个隔离级别！</span></span><br><span class="line"><span class="comment">     *   isolation = Isolation.READ_COMMITTED</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Transactional(readOnly = false ,rollbackFor = Exception.class , noRollbackFor = FileNotFoundException.class ,isolation = Isolation.READ_COMMITTED)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">changeInfo</span><span class="params">()</span> <span class="keyword">throws</span> FileNotFoundException &#123;</span><br><span class="line">        studentDao.updateAgeById(<span class="number">99</span>,<span class="number">1</span>);</span><br><span class="line">        <span class="keyword">new</span> <span class="title class_">FileInputStream</span>(<span class="string">&quot;xxx&quot;</span>);</span><br><span class="line">        studentDao.updateNameById(<span class="string">&quot;test3&quot;</span>,<span class="number">1</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<blockquote>
<p><strong>事务的隔离级别</strong></p>
</blockquote>
<ul>
<li>读未提交（Read uncommitted）: 事务可以读取被提交的数据，容易&#x3D;&#x3D;<strong>脏读</strong>&#x3D;&#x3D;(读取了另一个事务未提交的事务)，&#x3D;&#x3D;<strong>不可重复读</strong>&#x3D;&#x3D;（一个事务读取了另一个事务提交的修改数据）、&#x3D;&#x3D;<strong>幻读</strong>&#x3D;&#x3D;（一个事务读取了另一个事务插入的数据）</li>
<li>读已提交（Read committed）: 事务只能读取已经提交的数据，可以避免脏读，<strong>性能最好</strong>。</li>
<li>可重复读（Repeatable Read）：<strong>Mysql默认级别</strong>，同一个事务中，相同查询返回相同的结果集，可以避免脏读和不可重复读</li>
<li>串行化（Serializable）：<strong>最高的隔离级别，完全禁止并发</strong>，只允许一个事务执行完毕，下一个事务才可以执行。</li>
</ul>
<blockquote>
<p><strong>事务的传播特性</strong></p>
</blockquote>
<p><img src="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231027212940767.png" alt="image-20231027212940767"></p>
<p>方法A有事务，方法B也有事务，方法A调用了方法B</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 声明两个独立修改数据库的事务业务方法</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * propagation = Propagation.REQUIRED 父方法有事务，我们就加入到父方法的事务！</span></span><br><span class="line"><span class="comment">     *              最终是同一个事务！ 推荐使用默认值！！</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * propagation = Propagation.REQUIRES_NEW</span></span><br><span class="line"><span class="comment">     *               不管父方法是否有事务，我都是独立的事务！</span></span><br><span class="line"><span class="comment">     *               两个事务或者三个事务！</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * 还有其它三个参数，不常用</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Transactional(propagation = Propagation.REQUIRES_NEW)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">changeAge</span><span class="params">()</span>&#123;</span><br><span class="line">        studentDao.updateAgeById(<span class="number">998</span>,<span class="number">1</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Transactional(propagation = Propagation.REQUIRES_NEW)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">changeName</span><span class="params">()</span>&#123;</span><br><span class="line">        studentDao.updateNameById(<span class="string">&quot;二狗子&quot;</span>,<span class="number">1</span>);</span><br><span class="line">        <span class="type">int</span> i=<span class="number">1</span>/<span class="number">0</span>;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<p>另一个整合方法</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TopService</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> StudentService studentService;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Transactional</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span>  <span class="title function_">topService</span><span class="params">()</span>&#123;</span><br><span class="line">        studentService.changeAge();</span><br><span class="line">        studentService.changeName();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><img src="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231027213930981.png" alt="image-20231027213930981"></p>
<h2 id="六、spring总结"><a href="#六、spring总结" class="headerlink" title="六、spring总结"></a>六、spring总结</h2><p><img src="https://gitee.com/htt-sub/pic-go/raw/master/images/image-20231027214123267.png" alt="image-20231027214123267"></p>

      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      
        <div class="post-tags">
          
            <a href="/tags/spring/" rel="tag"># spring</a>
          
        </div>
      

      
      
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/2023/10/24/Maven/" rel="next" title="Maven工具">
                <i class="fa fa-chevron-left"></i> Maven工具
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/2023/10/28/Mybatis/" rel="prev" title="Mybatis">
                Mybatis <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </div>
  
  
  
  </article>



    <div class="post-spread">
      
    </div>
  </div>


          </div>
          


          

  



        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">
            文章目录
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview-wrap">
            站点概览
          </li>
        </ul>
      

      <section class="site-overview-wrap sidebar-panel">
        <div class="site-overview">
          <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
            
              <img class="site-author-image" itemprop="image"
                src="/images/avatar.png"
                alt="" />
            
              <p class="site-author-name" itemprop="name"></p>
              <p class="site-description motion-element" itemprop="description"></p>
          </div>

          <nav class="site-state motion-element">

            
              <div class="site-state-item site-state-posts">
              
                <a href="/archives">
              
                  <span class="site-state-item-count">10</span>
                  <span class="site-state-item-name">日志</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-categories">
                <a href="/categories/index.html">
                  <span class="site-state-item-count">6</span>
                  <span class="site-state-item-name">分类</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-tags">
                <a href="/tags/index.html">
                  <span class="site-state-item-count">8</span>
                  <span class="site-state-item-name">标签</span>
                </a>
              </div>
            

          </nav>

          

          

          
          

          
          

          

        </div>
      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#Spring"><span class="nav-number">1.</span> <span class="nav-text">Spring</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%8A%80%E6%9C%AF%E4%BD%93%E7%B3%BB%E7%BB%93%E6%9E%84"><span class="nav-number">1.1.</span> <span class="nav-text">技术体系结构</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E4%B8%80%E3%80%81SpringFramework%E4%BB%8B%E7%BB%8D"><span class="nav-number">1.2.</span> <span class="nav-text">一、SpringFramework介绍</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#1-Spring%E4%BC%98%E5%8A%BF"><span class="nav-number">1.2.1.</span> <span class="nav-text">1. Spring优势</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E4%BA%8C%E3%80%81SpringIOC%E5%AE%B9%E5%99%A8%E5%92%8C%E6%A0%B8%E5%BF%83%E6%A6%82%E5%BF%B5"><span class="nav-number">1.3.</span> <span class="nav-text">二、SpringIOC容器和核心概念</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#1-%E7%BB%84%E4%BB%B6"><span class="nav-number">1.3.1.</span> <span class="nav-text">1. 组件</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-%E6%9C%9F%E5%BE%85"><span class="nav-number">1.3.2.</span> <span class="nav-text">2. 期待</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3-Spring%E7%BB%84%E4%BB%B6%E7%AE%A1%E7%90%86%E5%8A%A8%E4%BD%9C"><span class="nav-number">1.3.3.</span> <span class="nav-text">3. Spring组件管理动作</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#4-SpringIOC%E5%AE%B9%E5%99%A8%E5%92%8C%E5%AE%B9%E5%99%A8%E5%AE%9E%E7%8E%B0"><span class="nav-number">1.3.4.</span> <span class="nav-text">4. SpringIOC容器和容器实现</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#5-SpringIOC%E5%AE%B9%E5%99%A8%E6%8E%A5%E5%8F%A3"><span class="nav-number">1.3.5.</span> <span class="nav-text">5. SpringIOC容器接口</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#6-%E4%B8%89%E7%A7%8D%E9%85%8D%E7%BD%AE%E6%96%B9%E5%BC%8F"><span class="nav-number">1.3.6.</span> <span class="nav-text">6. 三种配置方式</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#7-Spring-IoC-DI-%E6%A6%82%E5%BF%B5"><span class="nav-number">1.3.7.</span> <span class="nav-text">7. Spring IoC&#x2F; DI 概念</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E4%B8%89%E3%80%81SpringIOC%E5%AE%9E%E8%B7%B5%E5%92%8C%E5%BA%94%E7%94%A8"><span class="nav-number">1.4.</span> <span class="nav-text">三、SpringIOC实践和应用</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#SpringIoC%E5%AE%9E%E7%8E%B0%E6%AD%A5%E9%AA%A4"><span class="nav-number">1.4.1.</span> <span class="nav-text">SpringIoC实现步骤</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%9F%BA%E4%BA%8EXML%E9%85%8D%E7%BD%AE%E6%96%B9%E5%BC%8F%E7%BB%84%E4%BB%B6%E7%AE%A1%E7%90%86"><span class="nav-number">1.4.2.</span> <span class="nav-text">基于XML配置方式组件管理</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%9F%BA%E4%BA%8EXML%E7%9A%84IoC%E9%85%8D%E7%BD%AE"><span class="nav-number">1.4.2.1.</span> <span class="nav-text">基于XML的IoC配置</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%9F%BA%E4%BA%8EXML%E7%9A%84DI%E9%85%8D%E7%BD%AE"><span class="nav-number">1.4.2.2.</span> <span class="nav-text">基于XML的DI配置</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#IoC%E5%AE%B9%E5%99%A8%E5%88%9B%E5%BB%BA"><span class="nav-number">1.4.2.3.</span> <span class="nav-text">IoC容器创建</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E8%8E%B7%E5%8F%96Bean%E7%9A%84%E4%B8%89%E7%A7%8D%E6%96%B9%E6%B3%95"><span class="nav-number">1.4.2.4.</span> <span class="nav-text">获取Bean的三种方法</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E7%BB%84%E4%BB%B6Bean%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F"><span class="nav-number">1.4.2.5.</span> <span class="nav-text">组件Bean的生命周期</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#Bean%E7%9A%84%E4%BD%9C%E7%94%A8%E5%9F%9F"><span class="nav-number">1.4.2.6.</span> <span class="nav-text">Bean的作用域</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#factoryBean%E7%9A%84%E4%BD%BF%E7%94%A8"><span class="nav-number">1.4.2.7.</span> <span class="nav-text">factoryBean的使用</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#BeanFactory%E5%92%8CFactoryBean%E5%8C%BA%E5%88%AB"><span class="nav-number">1.4.2.8.</span> <span class="nav-text">BeanFactory和FactoryBean区别</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%9F%BA%E4%BA%8EXML-%E6%B3%A8%E8%A7%A3%E6%96%B9%E5%BC%8F%E7%AE%A1%E7%90%86Bean"><span class="nav-number">1.4.3.</span> <span class="nav-text">基于XML+注解方式管理Bean</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#Bean%E6%B3%A8%E8%A7%A3%E6%A0%87%E8%AE%B0%E5%92%8C%E6%89%AB%E6%8F%8F%EF%BC%88Ioc%EF%BC%89"><span class="nav-number">1.4.3.1.</span> <span class="nav-text">Bean注解标记和扫描（Ioc）</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E7%BB%84%E4%BB%B6Bean%E4%BD%9C%E7%94%A8%E5%9F%9F%E5%92%8C%E5%91%A8%E6%9C%9F%E6%96%B9%E6%B3%95"><span class="nav-number">1.4.3.2.</span> <span class="nav-text">组件Bean作用域和周期方法</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#Bean%E5%B1%9E%E6%80%A7%E8%B5%8B%E5%80%BC-%E5%BC%95%E7%94%A8%E7%B1%BB%E5%9E%8B%E8%87%AA%E5%8A%A8%E8%A3%85%E9%85%8DDI"><span class="nav-number">1.4.3.3.</span> <span class="nav-text">Bean属性赋值: 引用类型自动装配DI</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#Bean%E5%B1%9E%E6%80%A7%E8%B5%8B%E5%80%BC-%E5%9F%BA%E6%9C%AC%E7%B1%BB%E5%9E%8B%E5%B1%9E%E6%80%A7%E8%87%AA%E5%8A%A8%E8%A3%85%E9%85%8DDI"><span class="nav-number">1.4.3.4.</span> <span class="nav-text">Bean属性赋值: 基本类型属性自动装配DI</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%9F%BA%E4%BA%8E%E9%85%8D%E7%BD%AE%E7%B1%BB%E6%96%B9%E5%BC%8F%E7%AE%A1%E7%90%86Bean%EF%BC%8C%E5%AE%8C%E5%85%A8%E6%B3%A8%E8%A7%A3%E5%BC%80%E5%8F%91"><span class="nav-number">1.4.4.</span> <span class="nav-text">基于配置类方式管理Bean，完全注解开发</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E9%85%8D%E7%BD%AE%E7%B1%BB"><span class="nav-number">1.4.4.1.</span> <span class="nav-text">配置类</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#Bean%E7%9A%84%E7%BB%86%E8%8A%82"><span class="nav-number">1.4.4.2.</span> <span class="nav-text">@Bean的细节</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#Import"><span class="nav-number">1.4.4.3.</span> <span class="nav-text">@Import</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%95%B4%E5%90%88Spring-Test%E6%90%AD%E5%BB%BA%E6%B5%8B%E8%AF%95%E7%8E%AF%E5%A2%83"><span class="nav-number">1.4.5.</span> <span class="nav-text">整合Spring+Test搭建测试环境</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%9B%9B%E3%80%81SpringAOP"><span class="nav-number">1.5.</span> <span class="nav-text">四、SpringAOP</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BB%A3%E7%90%86%E6%A8%A1%E5%BC%8F"><span class="nav-number">1.5.1.</span> <span class="nav-text">代理模式</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86"><span class="nav-number">1.5.2.</span> <span class="nav-text">动态代理</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E9%9D%A2%E5%90%91%E5%88%87%E9%9D%A2%E7%BC%96%E7%A8%8B%EF%BC%88AOP%EF%BC%89"><span class="nav-number">1.5.3.</span> <span class="nav-text">面向切面编程（AOP）</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%9F%BA%E4%BA%8E%E6%B3%A8%E8%A7%A3%E5%AE%9E%E7%8E%B0AOP"><span class="nav-number">1.5.4.</span> <span class="nav-text">基于注解实现AOP</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%BA%95%E5%B1%82%E6%8A%80%E6%9C%AF%E7%BB%84%E6%88%90"><span class="nav-number">1.5.4.1.</span> <span class="nav-text">底层技术组成</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E8%8E%B7%E5%8F%96%E7%9B%AE%E6%A0%87%E6%96%B9%E6%B3%95%EF%BC%88%E5%88%87%E7%82%B9%EF%BC%89%E4%BF%A1%E6%81%AF"><span class="nav-number">1.5.4.2.</span> <span class="nav-text">获取目标方法（切点）信息</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%88%87%E7%82%B9%E8%A1%A8%E8%BE%BE%E5%BC%8F"><span class="nav-number">1.5.4.3.</span> <span class="nav-text">切点表达式</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E9%87%8D%E7%94%A8%E5%88%87%E7%82%B9%E8%A1%A8%E8%BE%BE%E5%BC%8F"><span class="nav-number">1.5.4.4.</span> <span class="nav-text">重用切点表达式</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E7%8E%AF%E7%BB%95%E9%80%9A%E7%9F%A5-%E6%9B%B4%E6%8E%A8%E8%8D%90%E5%88%86%E5%BC%80%E5%86%99%EF%BC%8C%E8%80%8C%E4%B8%8D%E6%98%AF%E7%8E%AF%E7%BB%95%E9%80%9A%E7%9F%A5"><span class="nav-number">1.5.4.5.</span> <span class="nav-text">环绕通知(更推荐分开写，而不是环绕通知)</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%88%87%E9%9D%A2%E4%BC%98%E5%85%88%E7%BA%A7%E8%AE%BE%E7%BD%AE"><span class="nav-number">1.5.4.6.</span> <span class="nav-text">切面优先级设置</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#Cglib%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86%E7%94%9F%E6%95%88"><span class="nav-number">1.5.4.7.</span> <span class="nav-text">Cglib动态代理生效</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#AOP%E6%B3%A8%E8%A7%A3%E6%80%BB%E7%BB%93"><span class="nav-number">1.5.4.8.</span> <span class="nav-text">AOP注解总结</span></a></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E4%BA%94%E3%80%81Spring%E5%A3%B0%E6%98%8E%E5%BC%8F%E4%BA%8B%E5%8A%A1"><span class="nav-number">1.6.</span> <span class="nav-text">五、Spring声明式事务</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%A3%B0%E6%98%8E%E5%BC%8F%E4%BA%8B%E5%8A%A1"><span class="nav-number">1.6.1.</span> <span class="nav-text">声明式事务</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Spring%E4%BA%8B%E5%8A%A1%E7%AE%A1%E7%90%86%E5%99%A8"><span class="nav-number">1.6.2.</span> <span class="nav-text">Spring事务管理器</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%9F%BA%E4%BA%8E%E6%B3%A8%E8%A7%A3%E7%9A%84%E5%A3%B0%E6%98%8E%E5%BC%8F%E4%BA%8B%E5%8A%A1"><span class="nav-number">1.6.2.1.</span> <span class="nav-text">基于注解的声明式事务</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%9F%BA%E6%9C%AC%E4%BA%8B%E5%8A%A1%E6%8E%A7%E5%88%B6"><span class="nav-number">1.6.2.2.</span> <span class="nav-text">基本事务控制</span></a></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%85%AD%E3%80%81spring%E6%80%BB%E7%BB%93"><span class="nav-number">1.7.</span> <span class="nav-text">六、spring总结</span></a></li></ol></li></ol></div>
            

          </div>
        </section>
      <!--/noindex-->
      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">&copy; <span itemprop="copyrightYear">2023</span>
  <span class="with-love">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">黄宏涛</span>

  
</div>


  <div class="powered-by">由 <a class="theme-link" target="_blank" href="https://hexo.io">Hexo</a> 强力驱动</div>



  <span class="post-meta-divider">|</span>



  <div class="theme-info">主题 &mdash; <a class="theme-link" target="_blank" href="https://github.com/iissnan/hexo-theme-next">NexT.Gemini</a> v5.1.4</div>




        







        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  


  











  
  
    <script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script>
  

  
  
    <script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>
  

  
  
    <script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>
  

  
  
    <script type="text/javascript" src="/lib/canvas-nest/canvas-nest.min.js"></script>
  


  


  <script type="text/javascript" src="/js/src/utils.js?v=5.1.4"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=5.1.4"></script>



  
  


  <script type="text/javascript" src="/js/src/affix.js?v=5.1.4"></script>

  <script type="text/javascript" src="/js/src/schemes/pisces.js?v=5.1.4"></script>



  
  <script type="text/javascript" src="/js/src/scrollspy.js?v=5.1.4"></script>
<script type="text/javascript" src="/js/src/post-details.js?v=5.1.4"></script>



  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.4"></script>



  


  




	





  





  












  





  

  

  

  
  

  

  

  

</body>
</html>
